﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BLL;
using DAL.Translator;
using System.ServiceModel;

namespace DAL
{
    /// <summary>
    /// Use EntityFramework to Implement RoleRepository
    /// </summary>
    public class RoleRepository : IRoleRepository
    {
        WorkShopEntities dbContext = new WorkShopEntities();
        /// <summary>
        /// Update Role to Database
        /// </summary>
        /// <param name="role"></param>
        public void UpdateRole(BLL.Role role)
        {
            var roleDE = dbContext.Role.Where(r => r.RoleId == role.RoleId).FirstOrDefault();
            if (roleDE == null)
            {
                throw new FaultException("This Role has been deleted.", new FaultCode("Role Deleted"));

            }
            else
            {
                roleDE.Authority.Clear();
                Authority roleAuthority = null;
                roleDE.RoleName = role.RoleName;
                roleDE.StatusId = (int)role.Status.StatusId;
                foreach (BLL.Authority item in role.Authorities)
                {
                    roleAuthority = dbContext.Authority.Where(a => a.AuthorityId == item.AuthorityId).FirstOrDefault<Authority>();
                    DAL.Authority authorityDE = (from Authority a in dbContext.Authority where a.AuthorityId == item.AuthorityId select a).SingleOrDefault<Authority>();
                    if (authorityDE == null)
                    {
                        throw new FaultException("The authority has changed, please select again.",new FaultCode("Authority Deleted"));

                    }
                    else
                    {
                        roleDE.Authority.Add(roleAuthority);
                    }
                }
                dbContext.SaveChanges();
            }

        }

        /// <summary>
        /// Save a New Role to Database
        /// </summary>
        /// <param name="role"></param>
        public void AddNewRole(BLL.Role role)
        {           
                var newRole = new DAL.Role();
                Authority roleAuthority = null;
                newRole.RoleName = role.RoleName;
                newRole.StatusId = (int)role.Status.StatusId;
                foreach (BLL.Authority item in role.Authorities)
                {
                    roleAuthority = dbContext.Authority.Where(a => a.AuthorityId == item.AuthorityId).FirstOrDefault<Authority>();
                    DAL.Authority authorityDE = (from Authority a in dbContext.Authority where a.AuthorityId == item.AuthorityId select a).SingleOrDefault<Authority>();
                    if (authorityDE == null)
                    {
                        throw new FaultException("The authority has changed, please select again.");
                    }
                    else
                    {
                        newRole.Authority.Add(roleAuthority);
                    }
                }
                dbContext.Role.AddObject(newRole);
                dbContext.SaveChanges();

        }

        /// <summary>
        /// Get Role by Current RoleId
        /// </summary>
        /// <param name="roleId"></param>
        /// <returns></returns>
        public BLL.Role GetRoleById(int roleId)
        {
            BLL.Role myRole = new BLL.Role();
            var role = (from m in dbContext.Role where m.RoleId == roleId select m).FirstOrDefault();
            if (role == null)
            {
                throw new FaultException("This role has been deleted.");
              
            }
            else
            {

                myRole = RoleTranslator.TranslateEntityToBusiness(role);
            }
            return myRole;
         
        }

        /// <summary>
        /// Get All Role Status
        /// </summary>
        /// <returns></returns>
        public List<BLL.Status> GetAllRoleStatus()
        {
            List<BLL.Status> statusList = new List<BLL.Status>();
            List<DAL.Status> edmStatusList = (from m in dbContext.Status select m).ToList<Status>();
            foreach (Status st in edmStatusList)
            {
                BLL.Status bllStatus = new BLL.Status();
                bllStatus.StatusId = st.StatusId;
                bllStatus.StatusName = st.StatusName;
                statusList.Add(bllStatus);
            }
            return statusList;
        }

        /// <summary>
        /// Search Role by Complex Conditions
        /// </summary>
        /// <param name="roleName"></param>
        /// <param name="firstName"></param>
        /// <param name="lastName"></param>
        /// <param name="status"></param>
        /// <param name="authorities"></param>
        /// <param name="sortExpression"></param>
        /// <param name="sortDirection"></param>
        /// <param name="PageSize"></param>
        /// <param name="PageIndex"></param>
        /// <param name="pageCnt"></param>
        /// <returns></returns>
        public List<BLL.Role> SearchRole(string roleName, string status, string authorities, string sortExpression, string sortDirection, double PageSize, int PageIndex, out int pageCnt)
        {
            List<BLL.Role> roleList = new List<BLL.Role>();
            pageCnt = 0;
            List<View_RoleInfo> roleDetails = dbContext.SearchRole(roleName,  status, authorities, sortExpression, sortDirection, PageSize, PageIndex).ToList<View_RoleInfo>();
            if (roleDetails != null)
            {
                foreach (var r in roleDetails)
                {
                    BLL.Role singleRole = new BLL.Role();
                    singleRole.Authorities = new List<BLL.Authority>();
                    BLL.Authority singleAuthority = new BLL.Authority();
                    singleRole.RoleId = r.rid;
                    singleRole.RoleName = r.roname;
                    singleAuthority.AuthorityName = r.auname;
                    singleAuthority.Level = new BLL.AuthorityLevel();
                    singleAuthority.Level.LevelName = r.lename;
                    pageCnt = r.pageCnt;
                    singleRole.Authorities.Add(singleAuthority);
                    roleList.Add(singleRole);
                }
            }
            return roleList;
        }

        /// <summary>
        /// Get Role Status by Current RoleId
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        public BLL.Status GetRoleStatusById(int Id)
        {
            Status statusDE = dbContext.Status.Where(p => p.StatusId == Id).FirstOrDefault();
            BLL.Status Status = new BLL.Status();
            Status.StatusId = statusDE.StatusId;
            Status.StatusName = statusDE.StatusName;
            return Status;
        }

        /// <summary>
        /// Delete Role from Database
        /// </summary>
        /// <param name="Id"></param>
        public void DeleteRole(int Id)
        {
            using (WorkShopEntities dbContext = new WorkShopEntities())
            {
                Role role = dbContext.Role.Where(p => p.RoleId == Id).FirstOrDefault();
                List<DAL.User> userList = new List<DAL.User>();
                userList = dbContext.User.Where(p => p.RoleId == Id).ToList();
                if (userList.Count != 0 && userList != null)
                {
                    throw new FaultException("This data is in use now.");
                }
                if (role == null)
                {
                    throw new FaultException("This role has been deleted.");
                }
                else
                {
                    role.Authority.Clear();
                    if (role != null)
                    {
                        dbContext.DeleteObject(role);
                        dbContext.SaveChanges();
                    }
                }
            }
        } 

        /// <summary>
        /// Update Role Status to Database
        /// </summary>
        /// <param name="roleList"></param>
        public void BatchUpdateRoleStatus(List<BLL.Role> roleList)
        {
            using (WorkShopEntities dbContext = new WorkShopEntities())
            {
                foreach (BLL.Role r in roleList)
                {
                    Role r_EF = dbContext.Role.Where(p => p.RoleId == r.RoleId).FirstOrDefault();
                    r_EF.StatusId = r.Status.StatusId;
                }
                dbContext.SaveChanges();
            }
        }


        /// <summary>
        /// Get All Role
        /// </summary>
        /// <param name="roleName"></param>
        /// <param name="status"></param>
        /// <returns></returns>
        public List<BLL.Role> GetAllRole(string roleName, int status)
        {
            using (WorkShopEntities dbContext = new WorkShopEntities())
            {
                var listDE = dbContext.Role.AsQueryable();
                List<BLL.Role> rolelistBE = new List<BLL.Role>();
                if (roleName.Trim().Length > 0)
                    listDE = from p in listDE
                             where p.RoleName.Contains(roleName)
                             select p;
                if (status != 0)
                    listDE = from p in listDE
                             where p.StatusId == status
                             select p;

                foreach (Role roleDE in listDE)
                {
                    BLL.Role roleBE = RoleTranslator.TranslateEntityToBusiness(roleDE);
                    rolelistBE.Add(roleBE);
                }
                return rolelistBE;
            }
        }

        /// <summary>
        /// Get All User Role
        /// </summary>
        /// <returns></returns>
        public List<BLL.Role> GetAllUserRole()
        {
            List<DAL.Role> listDAL = (from r in dbContext.Role where r.Status.StatusId == 1 select r).ToList<Role>();
            List<BLL.Role> roleList = new List<BLL.Role>();
            foreach (Role roleDE in listDAL)
            {
                BLL.Role roleBll = Translator.RoleTranslator.TranslateEntityToBusiness(roleDE);
                roleList.Add(roleBll);
            }
            return roleList;
        }        
    }
}
